React でページ内の目的の箇所まで自動スクロールさせる
「React で作ったページ内を自動スクロールさせたい」とたまに質問を受けるのでまとめました。
やりたいこと
React で作成したページに一覧が表示されているときに、一覧の最後までスクロールさせたい。 または目的の箇所までスクロールさせたい。
環境
- React 16.13.1
- TypeScript
コードと説明
- スクロールして表示したい箇所に React の Element をつくる (div など)
React.createRef()
で ref を作り、作った Element に ref をセットref.current.scrollIntoView()
で Element までスクロール
// <List /> の中身は CodePen のサンプルコード参照 const ListPage: React.FC = () => { // 表示するリストのデータを 100 個用意 (本当なら API 経由で取ってくる箇所) // const items: Item[] = [{ title: "number-0" }, { title: "number-1" }, ...] const items: Item[] = [...Array(100)].map((_, i) => { return { title: `number-${i}` } }); // ref を作成しスクロールさせたい場所にある Element にセット const ref = React.createRef<HTMLDivElement>() // このコールバックを呼び出して ref.current.scrollIntoView() を呼び出してスクロール const scrollToBottomOfList = React.useCallback(() => { ref!.current!.scrollIntoView({ behavior: 'smooth', block: 'end', }) // eslint-disable-next-line react-hooks/exhaustive-deps }, [ ref ]) // useEffect() 内はページが描画されたあとに呼び出される React.useEffect(()=>{ // ページが描画されたらリストの末尾までスクロール scrollToBottomOfList() // eslint-disable-next-line react-hooks/exhaustive-deps }, []) return ( <div> <List items={items} /> <div id="bottom-of-list" ref={ref} /> </div> ) }
このコードでは useEffect
を使ってページ描画時に自動スクロールしていますが、
scrollToBottomOfList()
を呼び出せばスクロールできるのでボタンがクリックされたときや、
ボタンをクリックした後データの読み込みが完了した後にスクロールすることもできます。
const handleClick = React.useCallback(() => { scrollToBottomOfList() }, []) // ... // <button onClick={handleClick} />いちばん下までスクロール</button>
スクロール先を変えたいときは ref={ref}
をセットしている Element の場所を変えるなどして対応します。
注意点
ページ内を強制的にスクロールするというのは、ページの利用者にとっては意図しない動作で使いにくいことがあります。 今表示されている箇所を見てるのに、勝手にスクロールされてどこを見てたのか分からなくなる、、なんて体験はよくあると思います。 (サンプルコードではページ表示時に自動スクロールしていますが) ユーザーのスクロールしたいという意思表示の操作があってからスクロールさせるようにしてください。